import ExcelJS from 'exceljs'

// 自动计算列宽，默认值为10
const autoWidthAction = (val,width = 10) =>{
  if(val == null){
    width = 10
  }else if(val.toString().charCodeAt(0) > 255){
    // charCodeAt() 方法返回字符串中规定索引（下标）处字符的 Unicode
    // 如果值为中文，列宽为字符串长度*2
    width = val.toString().length * 2
  }else{
    // 值为中文，列宽为字符串长度
    width = val.toString().length
  }
  return width
}

// 设置单元格样式
export function addCellStyle(cell, attr){
  const {bgColor,color, fontSize, horizontal, bold} = attr || {}
  // 单元格填充样式
  cell.fill = {
    type: 'pattern',   // 填充模式，pattern和gradient(渐变填充)
    pattern: 'solid',  // 填充类型
    fgColor: {argb: bgColor},  // 指定图案前景色，默认为黑色
    bgColor: {argb: bgColor},  // 指定图案背景色，默认为白色
  }
  // 单元格字体样式
  cell.font = {
    // ??（空值合并操作符）,当左侧值为 null 或 undefined 时，返回 ?? 符号右边的值
    bold: bold ?? true,         // 字体粗细，true/false
    size: fontSize ?? 11,       // 字体大小
    color: {argb: color},    // 字体颜色
  }
  // 单元格对齐方式
  cell.alignment = {
    vertical: 'middle',      // 垂直对齐方式
    wrapText: true,          // true-自动换行
    horizontal: horizontal ?? 'left',    // 水平对齐方式
  }
  // 单元格边框样式
  // cell.border = {
  //   top: {style:'double', color: {argb:'FF00FF00'}},
  //   left: {style:'double', color: {argb:'FF00FF00'}},
  //   bottom: {style:'double', color: {argb:'FF00FF00'}},
  //   right: {style:'double', color: {argb:'FF00FF00'}}
  // }
}

// 导出excel表格
export const exportExcel = async ({column,data,filename,autoWidth,format}) =>{
  // 创建工作簿
  const workbook = new ExcelJS.Workbook()
  // 设置工作簿信息
  workbook.creator = "liyoyo"
  workbook.title = filename
  workbook.created = new Date()
  workbook.modified = new Date()
  // 创建工作表
  // 使用 addWorksheet 函数的第二个参数可以指定工作表的标签颜色、网格线隐藏、冻结行和列等设置
  const worksheet = workbook.addWorksheet(filename)
  // 设置列名
  const columnsName = []
  column.forEach((item,index) =>{
    // 定义列对象，包括标题、键、宽度
    const obj = {
      header: item.label,
      key: item.name,
      width: null
    }
    if(autoWidth){
      // 获取到该列的标题以及该列下各个值的长度，取最大值作为该列的宽度
      const maxArr = [autoWidthAction(item.label)]
      data.forEach(it =>{
        const str = it[item.name] || ''
        if(str){
          maxArr.push(autoWidthAction(str))
        }
      })
      obj.width = Math.max(...maxArr) + 5
    }
    // 设置列名、键、宽度
    columnsName.push(obj)
  })
  worksheet.columns = columnsName
  // 添加行
  worksheet.addRows(data)
  // 写入文件
  const uint8Array = format == 'xlsx' ? await workbook.xlsx.writeBuffer() : await workbook.csv.writeBuffer()
  const blob = new Blob([uint8Array], {type: "application/octet-binary"})
  if('msSaveOrOpenBlob' in navigator){
    // window.navigator.msSaveOrOpenBlob()  该语句报错：window.navigator.msSaveOrOpenBlob is not a function
    // IE10 msSaveOrOpenBlob方法允许用户在客户端上保存文件，提供保存和打开按钮
    navigator.msSaveBlob(blob, filename + `.${format}`)
  }else{
    // 创建a标签下载
    const link = document.createElement('a')
    // href属性指定下载链接
    link.href = window.URL.createObjectURL(blob)
    // download属性指定文件名
    link.download = filename + `.${format}`
    // click()时间触发下载
    link.click()
    // 释放内存
    window.URL.revokeObjectURL(link.href)
  }
}

// 导出多级表头excel表格
export const exportMultiHeaderExcel = ({column,data,filename,autoWidth}) =>{
  // 创建excel
  const workbook = new ExcelJS.Workbook()
  // 创建工作簿
  const sheet = workbook.addWorksheet(filename)
  // 设置表头信息
  sheet.getRow(1).values = ['日期','配送信息',,,,,,]
  sheet.getRow(2).values = ['日期','姓名','性别','手机号','地址信息',,,]
  sheet.getRow(3).values = ['日期','姓名','性别','手机号','地址','城市','城区','邮编']

  const headers = []
  column.forEach(item =>{
    if(item.children){
      item.children.forEach(itemChild =>{
        if(itemChild.children){
          itemChild.children.forEach(it =>{
            const obj = {
              key: it.name, width: null
            }
            // 获取列标题的宽度
            const maxArr = [autoWidthAction(it.label)]
            data.forEach(ite =>{
              // 获取到该列的值
              const str = ite[it.name] || ''
              if(str){
                maxArr.push(autoWidthAction(str))
              }
            })
            obj.width = Math.max(...maxArr) + 5
            // 设置列名、键、宽度
            headers.push(obj)
          })
        }else{
          const obj = {
            key: itemChild.name, width: null
          }
          // 获取列标题的宽度
          const maxArr = [autoWidthAction(itemChild.label)]
          data.forEach(ite =>{
            // 获取到该列的值
            const str = ite[itemChild.name] || ''
            if(str){
              maxArr.push(autoWidthAction(str))
            }
          })
          obj.width = Math.max(...maxArr) + 5
          // 设置列名、键、宽度
          headers.push(obj)
        }
      })
    }else{
      const obj = {
        key: item.name, width: null
      }
      const maxArr = [autoWidthAction(item.label)]
      data.forEach(ite =>{
        const str = ite[item.name] || ''
        if(str){{
          maxArr.push(autoWidthAction(str))
        }}
      })
      obj.width = Math.max(...maxArr) + 5
      // 设置列名、键、宽度
      headers.push(obj)
    }
  })
  sheet.columns = headers
  sheet.addRows(data)

  // 合并单元格
  sheet.mergeCells('A1:A3')
  sheet.mergeCells('B1:H1')
  sheet.mergeCells('B2:B3')
  sheet.mergeCells('C2:C3')
  sheet.mergeCells('D2:D3')
  sheet.mergeCells('E2:H2')

  // 写入文件
  workbook.xlsx.writeBuffer()
    .then((data) =>{
      const blob = new Blob([data, {type: 'application/vnd.ms-excel'}])
      if('msSaveOrOpenBlob' in navigator){
        navigator.msSaveBlob(blob, filename + '.xlsx')
      }else{
        const link = document.createElement('a')
        link.href = window.URL.createObjectURL(blob)
        link.download = filename + '.xlsx'
        link.click()
        window.URL.revokeObjectURL(link.href)
      }
  })
}

// 自定义导出excel表格样式
export const exportStyleExcel = async ({column,data,filename,autoWidth,format,styleOptions}) =>{
  // 创建工作簿
  const workbook = new ExcelJS.Workbook()
  // 设置工作簿信息
  workbook.creator = "liyoyo"
  workbook.title = filename
  workbook.created = new Date()
  workbook.modified = new Date()
  // 创建工作表
  // 使用 addWorksheet 函数的第二个参数可以指定工作表的标签颜色、网格线隐藏、冻结行和列等设置
  const worksheet = workbook.addWorksheet(filename)
  // 设置列名
  const columnsName = []
  column.forEach((item,index) =>{
    // 定义列对象，包括标题、键、宽度
    const obj = {
      header: item.label,
      key: item.name,
      width: null
    }
    if(autoWidth){
      // 获取到该列的标题以及该列下各个值的长度，取最大值作为该列的宽度
      const maxArr = [autoWidthAction(item.label)]
      data.forEach(it =>{
        // 获取到该列的值
        const str = it[item.name] || ''
        if(str){
          maxArr.push(autoWidthAction(str))
        }
      })
      obj.width = Math.max(...maxArr) + 5
    }
    // 设置列名、键、宽度
    columnsName.push(obj)
  })
  worksheet.columns = columnsName
  // 添加行
  worksheet.addRows(data)
  // 设置表头颜色
  // 给表头添加背景色。因为表头是第一行，可以通过 getRow(1) 来获取表头这一行
  const headerRow = worksheet.getRow(1)
  // 通过 cell 设置样式，更精准
  const cellStyle = {
    bgColor: styleOptions.headerBgColor.split('#')[1] || 'dff8ff',
    color: styleOptions.headerFontColor.split('#')[1] || 'ff0000',
    fontSize: styleOptions.headerFontSize || 12,
    horizontal: styleOptions.headerHorizontal || 'left',
    bold: true,
  }
  headerRow.eachCell((cell) => addCellStyle(cell, cellStyle))
  // 写入文件
  const uint8Array = format == 'xlsx' ? await workbook.xlsx.writeBuffer() : await workbook.csv.writeBuffer()
  const blob = new Blob([uint8Array], {type: "application/octet-binary"})
  if('msSaveOrOpenBlob' in navigator){
    // window.navigator.msSaveOrOpenBlob()  该语句报错：window.navigator.msSaveOrOpenBlob is not a function
    // IE10 msSaveOrOpenBlob方法允许用户在客户端上保存文件，提供保存和打开按钮
    navigator.msSaveBlob(blob, filename + `.${format}`)
  }else{
    // 创建a标签下载
    const link = document.createElement('a')
    // href属性指定下载链接
    link.href = window.URL.createObjectURL(blob)
    // download属性指定文件名
    link.download = filename + `.${format}`
    // click()时间触发下载
    link.click()
    // 释放内存
    window.URL.revokeObjectURL(link.href)
  }
}
